//	Plazes-ASPI is an AS2.0 abstraction of the Plazes (http://www.plazes.com) XMLRPC-API
//		Copyright (C) 2006	Florian Mlodzik
//
//		This library is free software; you can redistribute it and/or
//		modify it under the terms of the GNU Lesser General Public
//		License as published by the Free Software Foundation; either
//		version 2.1 of the License, or (at your option) any later version.
//
//		This library is distributed in the hope that it will be useful,
//		but WITHOUT ANY WARRANTY; without even the implied warranty of
//		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the GNU
//		Lesser General Public License for more details.
//
//		You should have received a copy of the GNU Lesser General Public
//		License along with this library; if not, write to the Free Software
//		Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

// svn:keywords
// $URL: http://plazes-aspi.googlecode.com/svn/trunk/src/as2/com/orthogeneric/net/xmlrpc/XmlRpc.as $
// $Id: XmlRpc.as 4 2006-07-29 09:33:20Z florian.mlodzik $

/**
* The XmlRpc-class is used to do XMLRPC's complying to the <a href="http://www.xmlrpc.com/spec">XMLRPC specification</a>.
* It acts as an interface to remote server-endpoints.
* Actionscript variables are marshalled to typed methodcalls and returned methodresponses can be unmarshalled/serialized to Actionscript types.
* 
* @author florian.mlodzik@gmail.com
* @version 1.0a
* @see <a href="http://http://www.xmlrpc.com/">www.xmlrpc.com</a>
*/

// --> import
import ascb.util.Proxy;
import mx.events.EventDispatcher;
import com.orthogeneric.net.xmlrpc.XmlRpcMarshaller;
import com.orthogeneric.net.xmlrpc.events.XmlRpcResult;
import com.orthogeneric.net.xmlrpc.events.XmlRpcError;
import com.orthogeneric.net.xmlrpc.events.XmlRpcProgress;
// <-- import

class com.orthogeneric.net.xmlrpc.XmlRpc
{

	/** The XmlRpc-server endpoint */
	public var uri:String; 
	
	/**
	* The XmlRpc-class constructor.
	* 
	* @param	url The URL of the service endpoint
	*/
	public function XmlRpc(url:String)
	{
		uri = url;
		EventDispatcher.initialize(this);
		addEventListener("onXmlRpcResult", this);
		addEventListener("onXmlRpcError", this);
		addEventListener("onXmlRpcProgress", this);
	}
	
	/**
	* The instance-method to invoke remote xml procedure calls.
	* 
	* @param rMethod The name of the remote method to invoke
	* @param (optional) Any number of additional parameters for the remote method call
	*/
	public function callMethod(rMethod:String):Void
	{
		
		var xmlStr:String = XmlRpcMarshaller.marshallCall(rMethod, arguments.splice(1)); // get the methodcall-xml as string
		var rpcXml:XML = new XML(xmlStr);
				rpcXml.contentType = "text/xml";
				rpcXml.xmlDecl = "<?xml version=\"1.0\"?>";
				rpcXml.ignoreWhite = true;
				rpcXml.onLoad = Proxy.create(this, _onLoad, rpcXml, rMethod);
				rpcXml.sendAndLoad(uri, rpcXml);
				
		_initProgressInterval(rpcXml, rMethod);
	}
	
	/**
	* The instance-method to start an interval that is checking for the download-progresss of a xmlrpc-response.
	* A XmlRpcProgress-event will be dispatched with every intervalled call to the unnamed function.
	* 
	* @param x The XML-instance used for the rpc
	* @param rMethod The name of the remote method that has been invoked
	* 
	* Note: has not really been tested!
	* @exclude 
	*/
	private function _initProgressInterval(x:XML, rMethod:String):Void
	{
		var checkLoaded:Function = function (pXml:XML, me:XmlRpc, rM:String):Void
		{
			var bLoaded:Number = pXml.getBytesLoaded();
			var bTotal:Number = pXml.getBytesTotal();
			var pctg:Number = (bLoaded/bTotal)*100;
			me.dispatchEvent( new XmlRpcProgress(me, bLoaded, bTotal, pctg, rM) );
			if (pctg == 100) {
				//trace("method: "+rM+" progress: "+pctg+" - "+bLoaded+"/"+bTotal);
				clearInterval(pXml['__progressInterval']);
				delete pXml['__progressInterval'];
			}
		}
		x['__progressInterval'] = setInterval(checkLoaded, 10, x, this, rMethod); // backpack the interval to the xml-object
	}

	/**
	* The instance-method to receive the "onLoad"-event from the XML-instance that is used for the xmlrpc. 
	* Depending on the {@code success}-parameter and XML-instance's {@code status}-property a XmlRPcResult or a XmlRpcError event will be dispatched.
	* 
	* @param success The boolean whether the XML has been received
	* @param responseXml The XML-object holding the response
	* @param rMethod The name of the remote method that had been called
	* @exclude 
	*/
	private function _onLoad(success:Boolean, responseXml:XML, rMethod:String):Void 
	{
		clearInterval(this._progressIntvl);
		if (success) {
			if (responseXml.status == 0) {
				var result:Object = XmlRpcMarshaller.unmarshallResponse(responseXml); // parse the returned xml to serialize as-types
				dispatchEvent( new XmlRpcResult(this, result, responseXml, rMethod) );
			} else {
				dispatchEvent( new XmlRpcError(this, responseXml.status, responseXml, rMethod) );
			}
		} else {
			dispatchEvent( new XmlRpcError(this, -1, responseXml, rMethod) );
		}
	}
	
	/**
	* The instance-method to register an object as a listener to an event dispatched by this XmlRpc-instance.
	* Available events are:
	* 
	* 	"onXmlRpcResult" - dispatched when a result from a remote method has been received
	* 	"onXmlRpcProgress" - repeatedly dispatched during the retrieval of a method response
	* 	"onXmlRpcError" - dispatched when an error (i.e. endpoint is not available) has occurred
	* 
	*/
	public function addEventListener(event:String, listener:Object):Void
	{
	}
	
	/**
	* The instance-method to un-register an object as a listener to an event dispatched by this XmlRpc-instance.
	* 
	* @see addEventListener()
	*/
	public function removeEventListener(event:String, listener:Object):Void
	{
	}
	
	/**
	* The instance-method to dispatch an event by this XmlRpc-instance to all registered listeners.
	* The passed object should be of types XmlRpcResult, XmlRpcProgress or XmlRpcError.
	* 
	* @see XmlRpcResult 
	* @see XmlRpcProgress
	* @see XmlRpcError
	* @exclude
	*/
	public function dispatchEvent(evt:Object):Void
	{
	}
	
	/**
	* The instance-method that is being invoked when a result has been received from the xmlrpc
	* 
	* @see XmlRpcResult 
	*/
	public function onXmlRpcResult(evt:XmlRpcResult):Void
	{
	}
	
	/**
	* The instance-method that is repeatedly being invoked during the loading of a xmlrpc response.
	* 
	* @see XmlRpcProgress 
	*/
	public function onXmlRpcProgress(evt:XmlRpcProgress):Void
	{
	}
	
	/**
	* The instance-method that is being invoked when an error occured during the xmlrpc
	* 
	* @see XmlRpcError
	*/
	public function onXmlRpcError(evt:XmlRpcError):Void
	{
	}
}